﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Devart.Data.Oracle;

namespace Fugle
{
    public class ParameterSplitFunc
    {
        public static string Anasysis(string sql, OracleParameter[] parameters, CommandType cmdType)
        {
            if (parameters.Length == 0) return sql;
            if (cmdType != CommandType.Text) return sql;
            var sb = new StringBuilder(sql);
            var parameterList = SplitParameter(sb);
            if (parameterList.Count < parameters.Length)
                throw new Exception("解析的参数数量不匹配" + Environment.NewLine + sql);
            for (int i = parameters.Length - 1; i >= 0; i--)
            {
                var p2 = parameterList.FindAll(a => a.ParameterName.ToUpper() == ":" + parameters[i].ParameterName.ToUpper()).OrderByDescending(a => a.StartIndex).ToList();
                if (!p2.Any())
                    throw new Exception("未找到匹配的参数名称:" + parameters[i].ParameterName + Environment.NewLine + sql);
                p2.ForEach(p =>
                {
                    p.NewParameterName = ":P_" + i;
                });
                parameters[i].ParameterName = ":P_" + i;
            }
            for (int i = parameterList.Count - 1; i >= 0; i--)
            {
                var p = parameterList[i];
                //无对应参数不替换
                if (string.IsNullOrEmpty(p.NewParameterName))
                    continue;
                sb.Replace(p.ParameterName, p.NewParameterName, p.StartIndex, p.StopIndex - p.StartIndex);
            }
            return sb.ToString();
        }

        private static List<ParameterSplit> SplitParameter(StringBuilder sql)
        {
            var index = 0;
            var lenght = sql.Length;
            var list = new List<ParameterSplit>();

            while (index < lenght)
            {
                var index2 = GetStartSamb(index, lenght, sql);
                if (index2 == lenght)
                    break;
                var index3 = GetEndSamb(index2 + 1, lenght, sql);
                var parameterName = sql.ToString().Substring(index2, index3 - index2);
                index = index3 + 1;
                list.Add(new ParameterSplit()
                {
                    ParameterName = parameterName,
                    StartIndex = index2,
                    StopIndex = index3
                });
            }
            return list;
        }

        private static int GetStartSamb(int index, int lenght, StringBuilder sql)
        {
            while (index < lenght)
            {
                if (sql[index] == ':')
                    return index;
                index += 1;
            }
            return index;
        }

        private static int GetEndSamb(int index, int lenght, StringBuilder sql)
        {
            while (index < lenght)
            {
                var c = sql[index];
                if ((int)c > 127)
                {
                    index += 1;
                    continue;
                }
                if (('0' > c || c > '9') && ('A' > c || c > 'Z') && ('a' > c || c > 'z') && c != '_' && c != '#' && c != '$')
                {
                    break;
                }
                if (sql[index] == ' ')
                    return index;
                index += 1;
            }
            return index;
        }
    }
}
